import { useState, useCallback } from 'react';

import type { LoadingState } from '@/types/global';

interface UseLoadingReturn {
  isLoading: boolean;
  isSuccess: boolean;
  isError: boolean;
  state: LoadingState;
  setLoading: () => void;
  setSuccess: () => void;
  setError: () => void;
  reset: () => void;
  withLoading: <T>(asyncFn: () => Promise<T>) => Promise<T>;
}

export function useLoading(
  initialState: LoadingState = 'idle'
): UseLoadingReturn {
  const [state, setState] = useState<LoadingState>(initialState);

  const setLoading = useCallback(() => setState('loading'), []);
  const setSuccess = useCallback(() => setState('success'), []);
  const setError = useCallback(() => setState('error'), []);
  const reset = useCallback(() => setState('idle'), []);

  const withLoading = useCallback(
    async <T>(asyncFn: () => Promise<T>): Promise<T> => {
      try {
        setLoading();
        const result = await asyncFn();
        setSuccess();
        return result;
      } catch (error) {
        setError();
        throw error;
      }
    },
    [setLoading, setSuccess, setError]
  );

  return {
    isLoading: state === 'loading',
    isSuccess: state === 'success',
    isError: state === 'error',
    state,
    setLoading,
    setSuccess,
    setError,
    reset,
    withLoading,
  };
}
